package org.traffometer.traffobase.server;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import org.junit.Test;
import org.traffometer.common.data.TraffoPacket;
import org.traffometer.traffobase.model.FilePacketStore;
import org.traffometer.traffobase.model.PacketStore;

/**
 * Runs unit tests on the PacketListener class.
 * 
 * @author Robert S. Brewer
 */
public class TestPacketListener {

  /**
   * Test method for PacketListener constructor.
   */
  @Test
  public void testPacketListener() {
    PacketListener listener;
    
    listener = new PacketListener(null);
    assertEquals("Default server interface not picked", PacketListener.defaultServerInterface,
        listener.getServerInterface());
    assertEquals("Default server port not picked", PacketListener.defaultServerPort,
        listener.getPort());

    listener = new PacketListener("", 70000, null);
    assertEquals("Default server interface not picked", PacketListener.defaultServerInterface,
        listener.getServerInterface());
    assertEquals("Default server port not picked", PacketListener.defaultServerPort,
        listener.getPort());

    String server = "199.222.42.2";
    int port = 31001;
    FilePacketStore store = new FilePacketStore("test"); 
    listener = new PacketListener(server, port, store);
    assertEquals("Provided server interface not used", server, listener.getServerInterface());
    assertEquals("Provided server port not used", port, listener.getPort());
    assertSame("Provided PacketStore not used", store, listener.getPacketStore());
  }

  /**
   * Test method for handlePacketStream, which has stored packet byte representations that are
   * fed into the method instead of live network data.
   */
  @Test
  public void testHandlePacketStream() {
    // Represents an Account ID packet = "opendmtp"
    byte [] accountIDBytes = {-32, 18, 8, 111, 112, 101, 110, 100, 109, 116, 112};
    // Represents a Device ID packet = "mobile"
    byte [] deviceIDBytes = {-32, 19, 6, 109, 111, 98, 105, 108, 101};
    // Represents a TraffoPacket
    byte [] traffoPacketBytes = {-32, 112, 35, 97, -72, -77, 82, 15, -61, 123, 44, 69, 58, -64,
        -13, 97, -72, 68, 104, 15, -62, -96, 35, 69, 58, -63, 57, 102, 111, 111, 45, 109, 111, 98,
        105, 108, 101, 0};
    // Place to put the concatenation of the 3 packets
    byte [] streamBytes = new byte [accountIDBytes.length + deviceIDBytes.length +
                                    traffoPacketBytes.length];
    
    File storeFile = null;
    PacketListener listener = null;
    PacketStore store;
    ByteArrayInputStream input;
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    
    try {
      storeFile = File.createTempFile("traffobase", "aqua");
    }
    catch (IOException e) {
      fail("Unable to create temp file for testing: " + e);
    }
    store = new FilePacketStore(storeFile.getPath());
    
    listener = new PacketListener(store);
    // Gross code to append all the packets into one byte array
    System.arraycopy(accountIDBytes, 0, streamBytes, 0, accountIDBytes.length);
    System.arraycopy(deviceIDBytes, 0, streamBytes, accountIDBytes.length, deviceIDBytes.length);
    System.arraycopy(traffoPacketBytes, 0, streamBytes, accountIDBytes.length + 
        deviceIDBytes.length, traffoPacketBytes.length);
    input = new ByteArrayInputStream(streamBytes);
    listener.handlePacketStream(input, output);
    // Only one packet, this is shorthand
    for (TraffoPacket i : store.getPackets()) {
      assertEquals("Checks 1st lat", 21.28958, i.getLatitude1(), 0.000001);
      assertEquals("Checks 1st lon", -157.83244, i.getLongitude1(), 0.000001);
      assertEquals("Checks 1st time", 1161478387L, i.getTimeStamp1());

      assertEquals("Checks 2nd lat", 21.29077, i.getLatitude2(), 0.000001);
      assertEquals("Checks 2nd lon", -157.83714, i.getLongitude2(), 0.000001);
      assertEquals("Checks 2nd time", 1161478457L, i.getTimeStamp2());

      assertEquals("Checks Vehicle type", "foo-mobile", i.getVehicleType());
    }
  }
}
